/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package application;

import exception.ChargementPluginException;
import exception.FichierDeSerialisationException;
import exception.ChargementPluginException;
import exception.FichierDeSerialisationException;
import media.Media;
import bibliothequemultimedia.BibliothequeService;
import utils.Filtre;
import dao.MediaDAO;
import exception.AucunPluginException;
import exception.PluginDejaIntegreException;
import exception.SerializableException;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import javax.swing.JFileChooser;
import plugins.MediaPluginInterface;
import plugins.ChargeurPlugin;
import plugins.RecherchePluginInterface;
import utils.FilterFileChooser;
import vue.vueBiblio;

/**
 * Controlleur principal de l'application
 * @author Florian Minin & Khémon Beh
 */
public class ApplicationController implements ActionListener {

    private BibliothequeService biblio;
    private vueBiblio vue;

    /**
     * Constructeur
     * @param vue Vue principale
     * @param biblio Services de la bibliothèque multimedias
     */
    public ApplicationController(vueBiblio vue, BibliothequeService biblio) {
        this.biblio = biblio;
        this.vue = vue;
    }

    /**
     * Code executé au lancement de l'application
     */
    public void execute() {
        try {
            //On force l'intégration simultanée des pluginMedia dans la biblio
            //et dans la vue
            vue.integrerPlugins(biblio.deserializePluginMedia());
            //On récupère les informations des médias
            biblio.deserializeMedia();
        } //Lorsqu'on catch les exceptions on appelle les méthodes de la vue,
        //pour afficher les messages d'erreurs correspondant à l'erreur.
        catch (AucunPluginException ape) {
            vue.setErreurAucunPlugin();
        } catch (ChargementPluginException cpe) {
            vue.setErreurChargementPlugin();
        } catch (FichierDeSerialisationException fdse) {
            vue.setErreurFichierSerialisation();
        }
        //On charge les fiches média de tout les DAO de l'application
        vue.recupererFichesMedia(biblio.getAllDAO());
        //On rafraichit la liste des média
        rafraichissementListeMedia();
    }

    /**
     * Rafraichit les listes de média de l'application
     */
    private void rafraichissementListeMedia() {
        List<Media> listTemp;
        //On parcourt tout les DAO
        for (Entry<Integer, MediaDAO> mapDAOTemp : biblio.getAllDAO()) {
            listTemp = mapDAOTemp.getValue().getListMedia();
            //On met a jour la table
            vue.majTable(mapDAOTemp.getKey(), listTemp);
        }
    }

    /**
     * Code déclenché lors d'un clic sur un composant de la fenêtre
     * @param ae
     */
    public void actionPerformed(ActionEvent ae) {
        //on efface l'éventuel message d'erreur qui a pu être afficher à l'action
        //précedente.
        vue.setLabelErreurABlanc();
        //Appui sur le bouton d'ajout d'un media
        if (ae.getActionCommand().equals(vueBiblio.BTN_AJOUTER)) {
            //On met un en place un explorateur de fichier
            JFileChooser chooser = new JFileChooser();
            //On retire le filtre All Files mis par défaut
            chooser.setAcceptAllFileFilterUsed(false);
            //On récupère la liste des filtre de la bibliothèque et on les ajoute au JFileChooser
            for (Filtre currentFilter : biblio.getAllFilters()) {
                chooser.addChoosableFileFilter(currentFilter.getFiltre());
            }
            //On selectionne le filtre de la fenêtre courante.
            chooser.setFileFilter(biblio.getAllFilters().get(vue.indiceOngletSelectionne()).getFiltre());
            int returnVal = chooser.showOpenDialog(vue);
            //Si le fichier correspond au filtre
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                Filtre filtreMedia = null;
                //On va recupérer le filtre selectionné par l'utilisateur
                for (Filtre currentFilter : biblio.getAllFilters()) {
                    if (currentFilter.getFiltre().equals(chooser.getFileFilter())) {
                        filtreMedia = currentFilter;
                    }
                }

                //Recupération du type de média selectionné
                MediaDAO dao = biblio.getDAO(filtreMedia.getTypeMedia());

                //Creation du media
                Media m = dao.creeMediaGenerique();

                //On renseigne son nom ainsi que son chemin.
                m.setCheminSurDisque(cheminCompletFichier(chooser));
                m.setNomFichier(chooser.getSelectedFile().getName());

                //Ajout du media
                dao.ajouter(m);

                //Rafraichissement de la vue
                rafraichissementListeMedia();
            }
        } //Appui sur le bouton de consultation d'un media
        else if (ae.getActionCommand().equals(vueBiblio.BTN_CONSULTER)) {
            //Si une ligne est selectionnée
            if (vue.isLigneSelectionnee()) {
                //Récupération du média selectionné
                Media m = vue.getMediaSelectionne();
                //Ouverture de sa fiche média
                vue.ouvreUneFicheMedia(m, biblio.getDAO(m.getType()));
            } else {
                //Affichage d'un message d'erreur
                vue.setErreurAucuneLigneSelectionnee();
            }

        } //Appui sur le bouton de suppression d'un media
        else if (ae.getActionCommand().equals(vueBiblio.BTN_SUPPRIMER)) {
            //Si on a selectionné un média
            if (vue.isLigneSelectionnee()) {
                //On récupere le media selectionne
                Media media = vue.getMediaSelectionne();
                //On supprime le media de la bibliotheque
                biblio.getDAO(media.getType()).supprimerMedia(media);
                //On retire la ligne du tableau
                vue.supprimeLigneSelectionnee();
            } else {
                //Affichage d'un message d'erreur
                vue.setErreurAucuneLigneSelectionnee();
            }
        }
        //Appui sur le bouton Quitter
        else if (ae.getActionCommand().equals(vueBiblio.BTN_QUITTER)) {
            try {
                //On enregistre les média de l'application
                biblio.serializeMedia();
                //On enregistre le chemin des plugins chargé
                biblio.serializePluginMedia();
                //A faire : enregistrer les auteurs de chaque DAO
            } catch (SerializableException se) {
                //Erreur lors de la sérialisation
                vue.setErreurSerialisable();
            } catch (FichierDeSerialisationException fse) {
                //Erreur d'accès au fichier de sérialisation
                vue.setErreurFichierSerialisation();
            }
            //On termine l'application
            System.exit(0);

        }
        //Appui sur le bouton Ajouter un plugin
        else if (ae.getActionCommand().equals(vueBiblio.BTN_AJOUTER_PLUGIN)) {
            //On définit un sélécteur de fichier
            JFileChooser chooser = new JFileChooser();
            //On retire le filtre All Files mis par défaut
            chooser.setAcceptAllFileFilterUsed(false);
            //On fixe le filtre
            chooser.setFileFilter(new FilterFileChooser("Plugins", BibliothequeService.EXTENSIONS_PLUGIN));
            int returnVal = chooser.showOpenDialog(vue);
            if (returnVal == JFileChooser.APPROVE_OPTION) {
                List<String> cheminsFichier = new ArrayList<String>();
                //On ajoute a la liste le chemin du plugin a charger
                cheminsFichier.add(chooser.getSelectedFile().getAbsolutePath());
                //On crée un chargeur de plugin auquel on passe les chemins de fichiers a charger
                ChargeurPlugin manager = new ChargeurPlugin(cheminsFichier);
                try {
                    //On intègre les nouveau types de média
                    integrerPluginMedias(manager);
                    //On intègre le plugin de recherche
                    integrerPluginRecherche(manager);
                } catch (PluginDejaIntegreException pgde) {
                    vue.setErreurPluginIntegre();
                } catch (Exception e) {
                    vue.setErreurIntegrationPlugin();
                }
            }
        }
        //Lancement de la recherche
        else if(ae.getActionCommand().equals(vueBiblio.BTN_RECHERCHER)){
            
        }
    }

    /**
     * Gere l'intégration des nouveau médias a l'application
     * @param manager Permet de charger les données contenues dans le plugin
     * @throws PluginDejaIntegreException Exception lancée si le plugin est déja intégré
     * @throws Exception Exception lancée pour tout autre problème
     */
    private void integrerPluginMedias(ChargeurPlugin manager) throws PluginDejaIntegreException, Exception {
        //On récupère le classe souhaitée dans le Plugin.
        MediaPluginInterface[] listePlugin = manager.loadAllMediaPlugins();
        for (int i = 0; i < listePlugin.length; i++) {
            //On vérifie si le plugin n'est pas déja chargé
            if (!biblio.getAllTypes().contains(listePlugin[i].getTypeMedia())) {
                //On intègre le plugin a la bibliothèque
                biblio.integrerPlugin(listePlugin[i], manager.getFiles().get(i));
                //On intègre le plugin a l'interface
                vue.integrerPlugin(listePlugin[i]);
            } else {
                throw new PluginDejaIntegreException();
            }
        }
    }

    /**
     * Gere l'intégration d'une fonction de recherche a l'application
     * @param manager Permet de charger les données contenues dans le plugin
     * @throws Exception Exception lancée pour tout autre problème
     */
    private void integrerPluginRecherche(ChargeurPlugin manager) throws Exception {
        //On récupère la classe qui défini les actions du plugin
        RecherchePluginInterface pluginRecherche = manager.loadSearchPlugin();
        if (pluginRecherche != null) {
            //On intègre le menu a l'interface
            //vue.integrerPluginRecherche(pluginRecherche,this);
            //Problème de gestion des controller, décommenter cette ligne
            //pour tester la fenêtre de recherche
            pluginRecherche.lancerApplication(biblio.getAllDAO());
        }
    }

    /**
     * Méthode privée qui retourne le chemin choisit par le chooser
     * Réalise un traitement différent selon l'OS
     * @param chooser JFileChooser
     * @return <tt>String</tt> le chemin complet du fichier
     */
    private String cheminCompletFichier(JFileChooser chooser) {
        String directory = chooser.getCurrentDirectory().getAbsolutePath();
        String os = System.getProperty("os.name").toLowerCase();
        String cheminFichier = "";
        //Si l'OS est Windows on ajoute un caractère '\' entre
        //le répertoire et le fichier
        if ((os.indexOf("win") >= 0)) {
            cheminFichier = directory + "\\" + chooser.getSelectedFile().getName();
            //repertoireProgramme = directory + "\\";
        } //Si c'est MAC OS ou Unix/Linux on ajoute un caractère '/'
        else {
            cheminFichier = directory + "/" + chooser.getSelectedFile().getName();
            //repertoireProgramme = directory + "/";
        }
        return cheminFichier;
    }
}
